// umy-table mixins
// import { removal, typeIs } from '../../../utils/common'
import {removalDataObj as removal, typeIs} from '../../../../tools/utils/common'
export default {
  props: {
    data: {type: Array, default: () => []}, // 表格数据
    height: [String, Number],
    maxHeight: [String, Number],
    dialogData: {type: Array, default: () => []}, // 选择显示字段数组
    dataChangesScrollTop: {default: true, type: Boolean},  // 数据变化是否需要滚动到顶部
    stripe: {default: false, type: Boolean}, // 是否为斑马纹
    size: {default: '', type: String}, // Table 的尺寸
    fit: {default: true, type: Boolean}, // 列的宽度是否自撑开
    defaultSort: Object, // 默认的排序列的 prop 和顺序
    showHeader: {default: true, type: Boolean}, // 是否显示表头
    currentRowKey: [String, Number], // 当前行的 key，只写属性
    selectOnIndeterminate: {type: Boolean, default: true}, // 在多选表格中，当仅有部分行被选中时，点击表头的多选框时的行为
    emptyText: {default: '暂无数据', type: String}, // 空数据时显示的文本内容
    indent: {type: Number, default: 16}, // 展示树形数据时，树节点的缩进
    lazy: Boolean,
    load: Function,
    border: {default: true, type: Boolean}, // 是否显示纵向边框
    showSummary: {default: false, type: Boolean}, // 是否需要合计
    defaultExpandAll: {default: false, type: Boolean}, // 是否默认展开所有行，当 Table 包含展开行存在或者为树形表格时有效
    expandRowKeys: Array,
    treeProps: { default () { return { hasChildren: 'hasChildren', children: 'children' } }, type: Object }, // 渲染嵌套数据的配置选项
    treeConfig: [Boolean, Object],// 树形结构配置项
    totalOption: { default: () => [], type: Array }, // 需要合计的选项
    sumText: { default: '合计', type: String }, // 合计行名称
    fieldSort: { default: true, type: Boolean }, // 字段排序
    rowId: String, // 长用于大数据树
    rowKey: [String, Function], // 支持树类型的数据
    highlightCurrentRow: { default: true, type: Boolean }, // 是否要高亮当前行
    inverseCurrentRow: { default: false, type: Boolean }, // 是否需要反选高亮当前行
    showDialogIcon: { default: true, type: Boolean }, // 是否显示操作字段的上下移动按钮(侧滑框)
    moveDownIcon: { default: '', type: String }, // 下移按钮的图标(侧滑框)
    moveUpIcon: { default: '', type: String }, // 上移按钮的图标(侧滑框)
    showAmend: { default: false, type: Boolean }, // 是否显示修改字段名按钮(侧滑框)
    amendBtnIcon: { default: '', type: String }, // 修改字段按钮的图标(侧滑框)
    fieldTitle: { default: '选择显示字段', type: String }, // 弹框的标题(侧滑框)
    recordTableSelect: { default: false, type: Boolean }, // 是否记录表格的选项id(必须保证行ID存在，且唯一)
    headerDragStyle: { default: false, type: Boolean }, // 是否修改表格的头部拖动样式  | Boolean | false
    useVirtual: { default: false, type: Boolean }, // 是否开启虚拟滚动 | Boolean | false
    rowHeight: { default: 60, type: Number }, // 行高(必须要设置行高，否则会导致表格计算不正确)| Number | 60
    excessRows: { default: 3, type: Number }, //	可视区域上方和下方额外渲染的行数，行数越多表格接替渲染效果越好，但越耗性能	Number	3
    spanMethod: Function, // 合并行或列的计算方法 (注意，当开启useVirtual时，无效)
    tooltipEffect: { default: 'dark', type: String }, // tooltip effect 属性	String	dark/light
    beautifyTable: { default: false, type: Boolean }, // 美化表格，修改了样式
    tooltipPlacement: { default: 'top', type: String }, // Tooltip 的出现位置	String	top
    summaryMethod: Function, // 自定义的合计计算方法
    bigDataCheckbox: { default: false, type: Boolean }, // 大量数据时候（至少数据量大于3000条每页），表格存在selection选择列表时，是否开启解决全选卡顿（缓慢）问题，开启此项可能影响table-column的selectable属性功能，最好不要使用selectable
    rowClassName: [String, Function], // 行的 className 的回调方法，也可以使用字符串为所有行设置一个固定的 className。
    rowStyle: [Object, Function], // 行的 style 的回调方法
    cellClassName: [String, Function], // 行单元格的 className 的回调方法
    cellStyle: [Object, Function], // 行单元格的 style 的回调方法
    headerRowClassName: [String, Function], // 表头行的 className 的回调方法
    headerRowStyle: [Object, Function], // 表头行的 style 的回调方法
    headerCellClassName: [String, Function], // 表头单元格的 className 的回调方法
    headerCellStyle: [Object, Function], // 表头单元格的 style 的回调方法
    showHeaderOverflow: { type: [Boolean, String], default: null }, // 设置表头所有内容过长时显示为省略号
    showBodyOverflow: { type: [Boolean, String], default: null }, // 设置表体所有内容过长时显示为省略号
    fixedColumnsRoll: { default: false, type: Boolean }, // 表格有固定列,同时表格有合计,同时表格有横向滚动条，会导致固定列部分的横向滚动条不可拖动，是否需要解决此问题
    selectTrClass: String, //  如果当前行被选中了 type类型为selection，就给当前行给个类样式
    paginationShow: {default: false, type: Boolean}, // 是否需要分页器
    total: {default: 0, type: Number}, // 总条数
    pagerCount: { default: 5, type: Number }, // 页码按钮的数量，当总页数超过该值时会折叠
    pageSize:{ default: 10, type: Number }, // 每页条数
    currentPage: { default: 1, type: Number }, // 当前页
    pageSizes: { default: () => [10, 20, 30, 50], type: Array }, // 每页显示个数选择器的选项设置
    layout: { default: 'total, sizes, prev, pager, next, jumper', type: String } // 分页组件布局，子组件名用逗号分隔
  },
  methods: {
    // 分页器的事件
    handleSizeChange (val) {
      this.newPageSize = val
      this.$emit('handlePageSize', { size: this.newPageSize, page: this.newcurrentPage })
    },
    handleCurrentChange (val) {
      this.newcurrentPage = val
      this.$emit('handlePageSize', { size: this.newPageSize, page: this.newcurrentPage })
    },
    // 用于可展开表格与树形表格
    toggleRowExpansion (row, expanded) {
      this.$refs.singleTable.toggleRowExpansion(row, expanded)
    },
    // 合并行或列的计算方法
    arraySpanMethod ({ row, column, rowIndex, columnIndex }) {
      let objs = {row, column, rowIndex, columnIndex}
      // 是否有条件开启合并列
      if (typeof this.spanMethod === 'function') {
        return this.spanMethod(objs)
      } else {
        return ''
      }
    },

    // 当用户手动勾选全选 Checkbox 时触发的事件	selection
    selectAll (selection) {
      this.$emit('select-all', selection)
      // 当用户取消全选，就去找出表格当前的数据ID,然后去删除记录选择项ID数组对应的值
      if (this.recordTableSelect && this.data.length <= 1000) {
        if (selection.length === 0) {
          // this.data当前页的数据（当前表格数据）
          this.data.forEach(item => {
            this.tableSelectData.forEach((is, index) => {
              if (item.id === is) {
                this.tableSelectData.splice(index, 1)
              }
            })
          })
        }
        // 全选 就去添加记录
        if (selection.length > 0) {
          this.data.forEach(item => {
            if (item.id) {
              this.tableSelectData.push(item.id)
            }
          })
        }
        this.tableSelectData = JSON.parse(JSON.stringify(removal(this.tableSelectData)));
        // 这就是整个表格当前选中项（包含分页）
        this.$emit('table-select-change', this.tableSelectData)
      }
    },
    // 当用户手动勾选数据行的 Checkbox 时触发的事件
    plSelect (selection, row) {
      this.$emit('select', selection, row)
      // （执行删除选中节点操作）
      if (row.id && this.recordTableSelect && this.data.length <= 1000) {
        // 思路如下：  selection表示当前表格选中的节点数组, row表示当前点击的行节点
        // 1.如果selection中存在row ， 代表当前是勾上节点
        // 2.相反selection中不存在row ， 代表当前是在取消选中节点
        // 3.如果当前在取消选中节点，则falsData为空
        // 4.如果falsData为空，则去执行删除 -> 存放整个表格（包含分页）的数组中的值 （则 his.dats整个表格（包含分页）选中的节点数组节点ID）
        // 5. 这一步非常重要（判断当时节点是关闭，还是开启）
        let falsData = selection.filter(item => item.id === row.id)
        // 如果falsData数组为空，则代表当前节点被关闭了
        if (falsData.length === 0) {
          this.tableSelectData.forEach((item, index) => {
            if (item === row.id) {
              this.tableSelectData.splice(index, 1)
            }
          })
        }
        // 当前节点被开启
        if (falsData.length > 0) {
          this.tableSelectData.push(row.id);
        }
        this.tableSelectData = JSON.parse(JSON.stringify(removal(this.tableSelectData)));
        // 这就是整个表格当前选中项（包含分页）
        this.$emit('table-select-change', this.tableSelectData)
      }
    },
    // 当选择项发生变化时会触发该事件
    handleSelectionChange (val) {
      this.$emit('selection-change', val)
    },
    // 用于多选表格，切换某一行的选中状态，如果使用了第二个参数，则是设置这一行选中与否（selected 为 true 则选中）
    toggleRowSelection (rows) {
      if (rows && Array.isArray(rows)) {
        if (rows.length > 0 && this.$refs.singleTable) {
          rows.forEach(item => {
            if (item.selected) {
              this.$refs.singleTable.toggleRowSelection(item.row, item.selected, this.recordTableSelect)
            } else if (item.selected === false) {
              this.$refs.singleTable.toggleRowSelection(item.row, false, this.recordTableSelect)
            } else if (item.selected === undefined) {
              this.$refs.singleTable.toggleRowSelection(item.row, '', this.recordTableSelect)
            }
          })
        }
      } else {
        console.error('数据格式需要一个数组')
      }
    },
    // 用于多选表格，切换选中状态,适用于选中很多，取消很多
    partRowSelections (datas, state) {
      if (typeIs(state) === 'boolean' && this.useVirtual && this.bigDataCheckbox && this.rowKey) {
        this.$refs.singleTable.partRowSelections(datas, state)
      }
    },
    // 用于多选表格，切换所有行的选中状态
    toggleAllSelection () {
      if (this.$refs.singleTable) {
        this.$refs.singleTable.toggleAllSelection()
      } else {
        console.error('toggleAllSelection方法为找到，可能表格未加载完毕')
      }
    },
    // 用于多选表格，清空用户的选择
    clearSelection () {
      if (this.$refs.singleTable) {
        this.$refs.singleTable.clearSelection()
      } else {
        console.error('clearSelection方法为找到，可能表格未加载完毕')
      }
    },
    // 让表格滚动条回到顶部，和左侧
    pagingScrollTopLeft (top = 0, left = 0, type = '不倒计时') {
      this.$refs.singleTable.pagingScrollTop(top, left, type)
    },
    // 滚动表格到底部
    scrollBottom () {
      this.$refs.singleTable.scrollBottom()
    },
    // 合计的方法
    getSummaries (param) {
      if (typeof this.summaryMethod === 'function' && this.summaryMethod) {
        return this.summaryMethod(param)
      } else {
        const {columns, data} = param
        const sums = []
        columns.forEach((column, index) => {
          if (index === 0) {
            sums[index] = this.sumText
            return
          }
          const values = data.map(item => Number(item[column.property]))
          // 需要合并的选项
          const flas = this.totalOption.filter(item => item.label === column.label)
          if (!values.every(value => isNaN(value)) && flas.length > 0) {
            sums[index] = values.reduce((prev, curr) => {
              const value = Number(curr)
              if (!isNaN(value)) {
                return prev + curr
              } else {
                return prev
              }
            }, 0)
            sums[index] += flas[0].unit || ''
          } else {
            sums[index] = ''
          }
        })
        // 返回一个二维数组的表尾合计
        return [sums]
      }
    },
    // 打开自定义字段框
    plDialogOpens () {
      this._times = null
      this.$refs.plDialog.style.width = 300 + 'px'
      this._times = setTimeout(() => {
        this.plDialogFals = true
      }, 200)
      // 创建节点（主要用来弹出menu窗口时，不让起点击外面）
      this.aBox = document.createElement('div')
      this.aBox.className = 'modal-backdrop'
      this.aBox.style.display = 'block'
      this.aBox.onclick = () => {
        this.closeModal()
      }
      document.body.appendChild(this.aBox)
    },
    // 关闭自定义字段框（取消选择）
    closeModal () {
      this.plDialogFals = false
      clearTimeout(this._times)
      this.$refs.plDialog.style.width = 0 + 'px'
      this.aBox.style.display = 'none'
      this.clearNode()
      this.newDialogData = JSON.parse(JSON.stringify(this.dialogData))
    },
    // 确认按钮
    confirmField () {
      this.$emit('show-field', this.newDialogData)
      this.plDialogFals = false
      clearTimeout(this._times)
      this.$refs.plDialog.style.width = 0 + 'px'
      this.aBox.style.display = 'none'
      this.clearNode()
    },
    // 重置按钮
    reset () {
      this.$emit('reset', this.newDialogData)
      this.plDialogFals = false
      clearTimeout(this._times)
      this.$refs.plDialog.style.width = 0 + 'px'
      this.aBox.style.display = 'none'
      this.clearNode()
    },
    // 当某一行被点击时会触发该事件
    rowClick (row, column, event) {
      if (this.highlightCurrentRow) {
        this.$refs.singleTable.setCurrentRow(row);
      }
      this.$emit('row-click', row, column, event)
      // 如果当前节点存在current-row，再次点击时候那么就去掉current-row效果
      if (event.path && this.highlightCurrentRow && this.inverseCurrentRow) {
        event.path.forEach(item => {
          if (item && item.classList) {
            item.classList.forEach(its => {
              if (its === 'current-row') {
                this.$refs.singleTable.setCurrentRow();
              }
            })
          }
        })
      }
    },
    // 当某一行被双点击时
    rowDblclick (row, column, event) {
      this.$emit('row-dblclick', row, column, event)
    },
    // 用于单选表格，设定某一行为选中行
    setCurrentRow (row) {
      if (row) {
        this.$refs.singleTable.setCurrentRow(row);
      } else {
        this.$refs.singleTable.setCurrentRow();
      }
    },
    // 当用户对某一行展开或者关闭的时候会触发该事件
    expChang (row, expandedRows) {
      this.$emit('expand-change', row, expandedRows)
    },
    // 当某一列的表头被点击时会触发该事件
    headerClick (column, event) {
      this.$emit('header-click', column, event)
    },
    // 修改字段名按钮事件
    amendField (item, index) {
      this.$emit('amend-field', item, index)
    },
    // 表体滚动事件
    tableBodyScroll (table, event) {
      // 当表格滚动暴露滚动事件
      this.$emit('table-body-scroll', table, event)
    },
    // 当拖动表头改变了列的宽度的时候会触发该事件(newWidth, oldWidth, column, event)
    headerDragend (newWidth, oldWidth, column, event) {
      this.$emit('header-dragend', newWidth, oldWidth, column, event)
      this.doLayout('不执行滚动条')
    },
    // 对 Table 进行重新布局。当 Table 或其祖先元素由隐藏切换为显示时，可能需要调用此方法
    doLayout (type) {
      this.$refs.singleTable.doLayout()
      const {scrollTop, useVirtual, judgeFlse} = this.$refs.singleTable
      if (scrollTop && useVirtual && type !== '不执行滚动条') {
        if (judgeFlse) {
          this.$refs.singleTable.scrollBottom()
        } else {
          this.$refs.singleTable.pagingScrollTop(scrollTop)
        }
      }
    },
    // 删除节点
    clearNode () {
      // 删除节点
      let parent = this.aBox ? this.aBox.parentNode : ''
      parent && parent.removeChild(this.aBox)
      let doms = document.getElementsByClassName('modal-backdrop')
      if (doms.length > 0) {
        document.body.removeChild(doms[0])
      }
      this.aBox = null
    },
    // 当表格的排序条件发生变化的时候会触发该事件
    sortChange ({ column, prop, order }) {
      let objs = {column, prop, order}
      this.$emit('sort-change', objs)
    },
    // 当表格的当前行发生变化的时候会触发该事件
    currentChange (currentRow, oldCurrentRow) {
      this.$emit('current-change', currentRow, oldCurrentRow)
    },
    // 当表格的筛选条件发生变化的时候会触发该事件
    filterChange (filters) {
      this.$emit('filter-change', filters)
    },
    // 用于清空排序条件，数据会恢复成未排序的状态
    clearSort () {
      this.$refs.singleTable.clearSort()
    },
    // 不传入参数时用于清空所有过滤条件，数据会恢复成未过滤的状态
    clearFilter (columnKey) {
      this.$refs.singleTable.clearFilter(columnKey)
    },
    // 手动对 Table 进行排序
    sort (prop, order) {
      this.$refs.singleTable.sort(prop, order)
    },
    // 当单元格 hover 进入时会触发该事件
    cellMouseEnter (row, column, cell, event) {
      this.$emit('cell-mouse-enter', row, column, cell, event)
    },
    // 当单元格 hover 退出时会触发该事件
    cellMouseLeave (row, column, cell, event) {
      this.$emit('cell-mouse-leave', row, column, cell, event)
    },
    // 当某个单元格被点击时会触发该事件
    cellClick (row, column, cell, event) {
      this.$emit('cell-click', row, column, cell, event)
    },
    // 当某个单元格被双击击时会触发该事件
    cellDblclick (row, column, cell, event) {
      this.$emit('cell-dblclick', row, column, cell, event)
    },
    // 当某一行被鼠标右键点击时会触发该事件
    rowContextmenu (row, column, event) {
      this.$emit('row-contextmenu', row, column, event)
    },
    // 当某一列的表头被鼠标右键点击时触发该事件	column, event
    headerContextmenu (column, event) {
      this.$emit('header-contextmenu', column, event)
    },
    // 判断行是否为树形节点展开状态
    isTreeExpandByRow (row) {
      return this.$refs.singleTable.isTreeExpandByRow(row)
    },
    // 当虚拟树节点展开或收起时会触发该事件
    toggleTreeExpands (row, treeExpanded, event) {
      this.$emit('toggle-tree-expand', row, treeExpanded, event)
    },
    // 展开全部pl-table的树
    setAllTreeExpansion () {
      this.$refs.singleTable.setAllTreeExpansion()
    },
    // 关闭所有
    clearTreeExpand () {
      this.$refs.singleTable.clearTreeExpand()
    },
    // 获取已展开的节点
    getTreeExpandRecords () {
      return this.$refs.singleTable.getTreeExpandRecords()
    },
    // 设置展开树形节点
    setTreeExpansion (rows, expanded) {
      this.$refs.singleTable.setPlTreeExpansion(rows, expanded)
    },
    // 切换展开树形节点的状态
    toggleTreeExpansion (row) {
      this.$refs.singleTable.toggleTreeExpansion(row)
    }
  },
  // 生命周期结束
  beforeDestroy () {
  },
  // 如果使用了keep-alive
  deactivated () {
  },
  activated () {
  },
  watch: {
    data: {
      // 当需要监听一个对象的改变时，普通的watch方法无法监听到对象内部属性的改变，此时就需要deep属性对对象进行深度监听。
      // deep: true, // 不需要监听数组对象的变化
      immediate: true, // 如果我们需要在最初绑定值的时候也执行函数，则就需要用到immediate属性。
      handler (val) {
        if (!Array.isArray(val)) {
          throw new Error('表格数据需要的是数组格式，请检查你的数据格式');
        }
      }
    },
    dialogData: {
      deep: true,
      immediate: true,
      handler (val) {
        this.newDialogData = JSON.parse(JSON.stringify(val))
      }
    },
    currentPage (val) {
      this.newcurrentPage = val
    },
    pageSize (val) {
      this.newPageSize = val
    },
    height: {
      immediate: true,
      handler(value) {
        this.setHeight();
      }
    },
    maxHeight: {
      immediate: true,
      handler(value) {
        this.setHeight();
      }
    }
  }
}
